package cn.wm.codec;

import cn.wm.constant.ProtocolConstants;
import cn.wm.struct.Message;
import cn.wm.struct.MessageHeader;
import cn.wm.util.HessianUtils;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;

import java.util.List;

/**
 * MessageDecoder
 *
 * @author wm
 * @version 1.0
 * 2021/6/24 16:37
 **/
public class MessageDecoder extends ByteToMessageDecoder {

    @Override
    protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> list) throws Exception {
        try {
            int begin;
            // 找到协议开始的位置
            while (true) {
                /**
                 *标记一下协议包开始的位置
                 * 然后读取一个int值(4byte)，判断读取到的值是否和协议头(MagicWord魔数)相等
                 * 相等的话跳出循环
                 * 不相等的话则以 1byte 为步长向后位移直到取到 MagicWord
                 */
                // 本次协议包开始的位置
                begin = byteBuf.readerIndex();
                // 标记本次协议包开始的位置
                byteBuf.markReaderIndex();
                if (byteBuf.readInt() == ProtocolConstants.PROTOCOL_MAGIC_WORD) {
                    break;
                }
                // 没有读到 MAGIC_WORD，那么就读取下一个字节
                byteBuf.resetReaderIndex();
                byteBuf.readByte();
            }
            // 协议包头长度
            int headerLength = byteBuf.readInt();
            // 协议包头数据还未到齐，回到协议开始的位置，等待数据到齐
            if (byteBuf.readableBytes() < headerLength) {
                byteBuf.readerIndex(begin);
                return;
            }
            // 协议内容长度
            int bodyLength = byteBuf.readInt();
            // 协议包内容数据还未到齐，回到协议开始的位置，等待数据到齐
            if (byteBuf.readableBytes() < bodyLength) {
                byteBuf.readerIndex(begin);
                return;
            }
            // 读取字节
            byte[] headerCont = new byte[headerLength];
            byteBuf.readBytes(headerCont);
            byte[] bodyCont = new byte[bodyLength];
            byteBuf.readBytes(bodyCont);

            //转化为自定义协议
            Message msg = new Message();
            msg.setHeader(HessianUtils.read(headerCont, MessageHeader.class));
            msg.setBody(bodyCont);
            list.add(msg);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
